<?php
interface Logger{
	
	/**
	 * @param integer $level
	 * @param string $messages
	 * @param string $file
	 * @param integer $line
	 */
	public function log($level,$messages,$file,$line);
}

class Logging{
	
	public static $FATAL = 100;
	
	public static $ERROR = 80;
	
	public static $WARN = 60;
	
	public static $NOTICE = 40;
	
	public static $INFO = 20;
	
	public static $DEBUG = 0;
	
	/**
	 * @var Logging
	 */
	private static $instance = null;
	
	/**
	 * List the available validators.
	 *
	 * @return array
	 */
	public static function loggers(){
		cmspad_import('cache.DirectoryCache');
		$cache = new DirectoryCache('cmspad_loggers',dirname(__FILE__) . '/logging/',DirectoryCache::$MODE_FILE,false);
		$loggers = array();
		foreach($cache->value() as $f){
			$l = strlen($f) > 5?strlen($f) - 4:0;
			if($l > 0 && substr($f,$l) == '.php'){
				$loggers[] = substr($f,0,$l);
			}
		}
		return $loggers;
	}
	
	/**
	 * @return Logging
	 */
	public static function getInstance(){
		global $_CONFIG;
		if(!self::$instance){
			if(isset($_CONFIG['LOGGING']['TYPE'])){
				$logger = $_CONFIG['LOGGING']['TYPE'];
			}else{
				$logger = 'file';
			}
			$loggerFile = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'logging' . DIRECTORY_SEPARATOR . $logger . '.php';
			if(file_exists($loggerFile)){
				require ($loggerFile);
				if(class_exists('cmspad_logger_' . $logger)){
					self::$instance = new Logging($logger);
				}else{
					trigger_error('Logger class not found: ' . $logger,E_USER_ERROR);
					return false;
				}
			}else{
				trigger_error('Logger file not found: ' . $logger,E_USER_ERROR);
				return false;
			}
		}
		return self::$instance;
	}
	
	/**
	 * @var Logger
	 */
	private $logger;
	
	private $released;
	
	private function __construct($type){
		$class = 'cmspad_logger_' . $type;
		$this->logger = new $class();
		$this->released = false;
		set_error_handler(array(&$this,'error_handler'));
		register_shutdown_function(array(&$this,'__destruct'));
	}
	
	public function __destruct(){
		if(!$this->released){
			unset($this->logger);
			restore_error_handler();
			$this->released = true;
		}
	}
	
	public function debug($messages,$file,$line){
		$this->logger->log(self::$DEBUG,$messages,$file,$line);
	}
	
	public function error($messages,$file,$line){
		$this->logger->log(self::$ERROR,$messages,$file,$line);
	}
	
	public function fatal($messages,$file,$line){
		$this->logger->log(self::$FATAL,$messages,$file,$line);
	}
	
	public function info($messages,$file,$line){
		$this->logger->log(self::$INFO,$messages,$file,$line);
	}
	
	public function notice($messages,$file,$line){
		$this->logger->log(self::$NOTICE,$messages,$file,$line);
	}
	
	public function warn($messages,$file,$line){
		$this->logger->log(self::$WARN,$messages,$file,$line);
	}
	
	public function error_handler($no,$msg,$file,$line){
		global $_CONFIG;
		switch($no){
			case E_ERROR:
			case E_PARSE:
			case E_CORE_ERROR:
			case E_COMPILE_ERROR:
			case E_USER_ERROR:
				$level = self::$ERROR;
				break;
			case E_WARNING:
			case E_CORE_WARNING:
			case E_COMPILE_WARNING:
			case E_USER_WARNING:
				$level = self::$WARN;
				break;
			case E_NOTICE:
			case E_USER_NOTICE:
			case E_STRICT:
				$level = self::$NOTICE;
				break;
			case E_RECOVERABLE_ERROR:
				$level = self::$FATAL;
				break;
			default:
				$level = self::$DEBUG;
				break;
		}
		$this->logger->log($level,$msg,$file,$line);
		
		// Display Errors
		if(isset($_CONFIG['LOGGING']['SHOW']) && $_CONFIG['LOGGING']['SHOW'] !== false){
			$dir = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'logging' . DIRECTORY_SEPARATOR;
			if(file_exists($dir . 'logging.tpl')){
				$tplclass = cmspad_import('template.TemplateEngine');
				$template = new $tplclass($dir);
				$template->addVariable('type',$no);
				$template->addVariable('title',$_CONFIG['LOGGING']['SHOW']);
				$template->addVariable('message',$msg);
				$template->addVariable('file',$file);
				$template->addVariable('line',$line);
				$template->output('logging.tpl');
				if(isset($_CONFIG['LOGGING']['EXIT']) && $_CONFIG['LOGGING']['EXIT']){
					exit();
				}
			}else{
				return false;
			}
		}
		return true;
	}
}
?>